//
// DotNetNuke - http://www.dotnetnuke.com
// Copyright (c) 2002-2010
// by Perpetual Motion Interactive Systems Inc. ( http://www.perpetualmotion.ca )
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 
// to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions 
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
// DEALINGS IN THE SOFTWARE.
//

using System;
using System.Threading;
using System.Web.Compilation;
namespace DotNetNuke.Services.Scheduling.DNNScheduling
{
	public class ProcessGroup
	{
		private static int numberOfProcessesInQueue = 0;
		private static int numberOfProcesses = 0;
		private static int processesCompleted;
		private static int ticksElapsed;
		static int GetTicksElapsed {
			get { return ticksElapsed; }
		}
		static int GetProcessesCompleted {
			get { return processesCompleted; }
		}
		static int GetProcessesInQueue {
			get { return numberOfProcessesInQueue; }
		}
		public event CompletedEventHandler Completed;
		public delegate void CompletedEventHandler();
		public void Run(ScheduleHistoryItem objScheduleHistoryItem)
		{
			SchedulerClient Process = null;
			try {
				ticksElapsed = Environment.TickCount - ticksElapsed;
				Process = GetSchedulerClient(objScheduleHistoryItem.TypeFullName, objScheduleHistoryItem);
				Process.ScheduleHistoryItem = objScheduleHistoryItem;
				Process.ProcessStarted += new WorkStarted(DotNetNuke.Services.Scheduling.DNNScheduling.Scheduler.CoreScheduler.WorkStarted);
				Process.ProcessProgressing += new WorkProgressing(DotNetNuke.Services.Scheduling.DNNScheduling.Scheduler.CoreScheduler.WorkProgressing);
				Process.ProcessCompleted += new WorkCompleted(DotNetNuke.Services.Scheduling.DNNScheduling.Scheduler.CoreScheduler.WorkCompleted);
				Process.ProcessErrored += new WorkErrored(DotNetNuke.Services.Scheduling.DNNScheduling.Scheduler.CoreScheduler.WorkErrored);
				Process.Started();
				try {
					Process.ScheduleHistoryItem.Succeeded = false;
					Process.DoWork();
				} catch (Exception exc) {
					if (Process != null) {
						if (Process.ScheduleHistoryItem != null) {
							Process.ScheduleHistoryItem.Succeeded = false;
						}
						Process.Errored(ref exc);
					}
				}
				if (Process.ScheduleHistoryItem.Succeeded == true) {
					Process.Completed();
				}
				if (processesCompleted == numberOfProcesses) {
					if (processesCompleted == numberOfProcesses) {
						ticksElapsed = Environment.TickCount - ticksElapsed;
						if (Completed != null) {
							Completed();
						}
					}
				}
			} catch (Exception exc) {
				if (Process != null) {
					if (Process.ScheduleHistoryItem != null) {
						Process.ScheduleHistoryItem.Succeeded = false;
					}
					Process.Errored(ref exc);
				}
			} finally {
				numberOfProcessesInQueue -= 1;
				processesCompleted += 1;
			}
		}
		private SchedulerClient GetSchedulerClient(string strProcess, ScheduleHistoryItem objScheduleHistoryItem)
		{
			Type t = BuildManager.GetType(strProcess, true, true);
			ScheduleHistoryItem[] param = new ScheduleHistoryItem[1];
			param[0] = objScheduleHistoryItem;
			Type[] types = new Type[1];
			types[0] = typeof(ScheduleHistoryItem);
			System.Reflection.ConstructorInfo objConstructor;
			objConstructor = t.GetConstructor(types);
			return (SchedulerClient)objConstructor.Invoke(param);
		}
		private void RunPooledThread(object objScheduleHistoryItem)
		{
			Run((ScheduleHistoryItem)objScheduleHistoryItem);
		}
		public void AddQueueUserWorkItem(ScheduleItem s)
		{
			numberOfProcessesInQueue += 1;
			numberOfProcesses += 1;
			ScheduleHistoryItem obj = new ScheduleHistoryItem(s);
			try {
				WaitCallback callback = new WaitCallback(RunPooledThread);
				ThreadPool.QueueUserWorkItem(callback, (object)obj);
				Thread.Sleep(1000);
			} catch (Exception exc) {
				Services.Exceptions.Exceptions.ProcessSchedulerException(exc);
			}
		}

	}
}
